/* Request ID: 3631be47e51af91b8d275e0c763d07aa (05/18/2024 2:46pm) (minifier disabled) (PclBEsIgDAXQq3SnM7bJgVw4CL+CEwITQrm+O9/28RWM11rcoXrotFH0cyRcJOXCykFACuc+31LiK3sV/g97RgXHZuARrXQffFpThyb6jn27PVKLs0KdpMXgpSllw0mGLiHivm/PHw==) */ /*global grecaptcha:true */ (function($, LW) { // lib functions specific to frontend LW.lib = LW.lib || {}; var $body = $('body'); LW.lib.getICalDate = function(ts) { var dt; if (!ts) return ''; dt = new LW.lib.LWCDate(ts, 0); return dt.getFormattedDate('Ymd') + 'T' + dt.getFormattedDate('His') + 'Z'; }; // data props: ts_start, ts_end, is_all_day, title, summary, location LW.lib.getAddToGoogleLink = function(data) { var lnk = 'http://www.google.com/calendar/event?action=TEMPLATE&', args = [], sdate = this.getICalDate(data.ts_start), ts_end, edate; // google requires an end time, so use a sensible value if no data.ts_end if (data.ts_end) { ts_end = data.ts_end; } else { ts_end = (data.is_all_day) ? data.ts_start + 3600 * 24 : data.ts_start + 3600; } edate = this.getICalDate(ts_end); args.push('text=' + encodeURIComponent(data.title)); args.push('dates=' + sdate + '/' + edate); if (data.summary) { args.push('details=' + encodeURIComponent(LW.lib.htmlDecode(data.summary))); } if (data.location) { args.push('location=' + encodeURIComponent(data.location)); } return lnk + args.join('&') + '&trp=false&sprop=&sprop=name:'; }; // docs here: // https://docs.google.com/a/ikemcg.com/document/d/1scDk4WxGzDSGAF6OWiRkKwdQg9zD8kDReTH9cvTZnVo/edit LW.lib.getAddToYahooLink = function(data) { var lnk = 'http://calendar.yahoo.com/?v=60&view=d&type=20&', args = []; args.push('title=' + encodeURIComponent(data.title)); args.push('st=' + this.getICalDate(data.ts_start)); if (data.ts_end) { // using ET doesn't appear to work - Yahoo doesn't apply a local time shift, even with the Z args.push('et=' + this.getICalDate(data.ts_end)); } if (data.summary) { args.push('desc=' + encodeURIComponent(LW.lib.htmlDecode(data.summary))); } if (data.location) { args.push('in_loc=' + encodeURIComponent(data.location)); } return lnk + args.join('&'); }; // add frontend-specific plugins $.fn.extend({ // initialize all frontend behavior within a specific region. This plugin is called on the entire // page content on page load, and on each editable region when editing stops - on save or cancel initFrontendRegion: function() { return this.each(function() { var $region = $(this); var process = { // look up anything that needs JS processing captcha: { elements: $region.find('.lw_captcha') } }; $.each(process, function(fn, data) { // with each if (data.elements.length) { // if there are elements data.elements[fn](data.settings); // apply the function } }); // show image captions $region.find('.lw_image[data-caption-enabled="true"][data-caption]').each(function() { var $this = $(this), $sibling = ($this.parent().hasClass('lw_preview_image')) ? $this.parent() : $this; $('
') .width($this.width()) .text($this.attr('data-caption')) .insertAfter($sibling); }); // force all external widget links to open in a new tab/window. // ignore nav widgets which have their own PHP rule for this // // there is a public.config.php option that disables this behavior if (!LW.disable_widget_link_targets) { $region .find('.lw_widget:not(.lw_widget_type_navigation) a[href^="http"]:not([target])').each(function() { var $this = $(this); var url = $this.attr('href'); // add target="_blank" if url is to external site if (!LW.lib.hasCurrentDomainAndTld(url)) { $this.attr('target', '_blank'); } }); } // handle all language toggle elements $('*[class^="lw_language_"]').on('click', function() { var selected_language = $(this).attr('class').split(' ').filter(function(str) { return str.indexOf('lw_language_') === 0; }); selected_language = selected_language.join('').substring(12); if (selected_language) { if (selected_language === 'english') { LW.lib.setCookie(LW.cookie_prefix + 'lang', '', 0, '/', LW.cookie_host, false); } else { var expires = new Date(new Date().setYear(new Date().getFullYear() + 1)); LW.lib.setCookie(LW.cookie_prefix + 'lang', selected_language, expires, '/', LW.cookie_host, false); } location.reload(); } return false; }); // handle data-background-image $('div[data-background-image]').each(function() { // for each data-background-image if (LW.lib.hasWebPSupport()) { // if webp supported by server and browser if ($(this).attr('data-background-image').match(/\.jp[e]*g/)) { // swap in webp for jp(e)g $(this).attr('data-background-image', $(this).attr('data-background-image').replace(/\.jp[e]*g/i, '.webp')); } } $(this).css('background-image', 'url("' + $(this).attr('data-background-image') + '")'); // apply background image $(this).removeAttr('data-background-image'); // remove the data attribute }); }); } }); LW.captcha_requested = false; LW.captcha_loaded = false; $.widget('lw.captcha', { widget_id: null, options: { attachSubmitHandler: true }, _create: function() { var that = this; var $el = this.element; var sitekey = this.sitekey = $el.attr('data-sitekey'); var version = this.version = parseInt($el.attr('data-version')) || 0; var $form = this.$form = $el.closest('form'); var interval_id; // do nothing if the element is not empty if ($.trim($el.html())) return; if (version === 0 || version === 2) { // for Recaptcha 2 interval_id = setInterval(function() { if (LW.captcha_loaded) { clearInterval(interval_id); // initialize Recaptcha that.widget_id = grecaptcha.render($el.get(0), { 'sitekey': sitekey }); $('#g-recaptcha-response').attr('aria-hidden', true).attr('aria-label', 'hidden captcha field'); } }, 50); if (!LW.captcha_requested) { window.lwCaptchaOnloadCallback = function() { LW.captcha_loaded = true; }; $.getScript('http' + (window.location.protocol === 'https:' ? 's' : '') + '://www.google.com/recaptcha/api.js?onload=lwCaptchaOnloadCallback&render=explicit'); LW.captcha_requested = true; } } else if (version === 3) { // else for Recaptcha 3 $el.hide(); // hide the captcha under 3 because it adds whitespace // add handler to call recaptcha's execute method on submit. This method must be called immediately // before submit. Adding this handler is the default but it doesn't work for forms that have their // own submit handler, which is the case for all LW forms module forms and the saveandshare form. // forms with existing submit handlers must call this plugin's execute function if (!$form.hasClass('lw_forms_form') && this.options.attachSubmitHandler === true) { if (LW.captcha_loaded) { this.attachSubmitHandler($form, sitekey); } else { interval_id = setInterval(function() { if (LW.captcha_loaded) { clearInterval(interval_id); that.attachSubmitHandler($form, sitekey); } }, 50); } } if (!LW.captcha_requested) { window.lwCaptchaOnloadCallback = function() { LW.captcha_loaded = true; }; $.getScript('http' + (window.location.protocol === 'https:' ? 's' : '') + '://www.google.com/recaptcha/api.js?onload=lwCaptchaOnloadCallback&render=' + sitekey); LW.captcha_requested = true; } } }, attachSubmitHandler: function($form, sitekey) { // initialize Recaptcha $form.off('submit').on('submit', function(event) { event.preventDefault(); grecaptcha.ready(function() { grecaptcha.execute(sitekey, { action: 'lw_form' }).then(function(token) { $form.find('input[name="token"],input[name="action"]').remove(); $form.prepend(''); $form.prepend(''); $form.unbind('submit').submit(); }); }); }); }, // used by LW forms JS (livewhale/theme/core/scripts/forms.js) execute: function(callback) { var that = this; if (!$.isFunction(callback)) { callback = $.noop; } if (this.version === 3) { grecaptcha.ready(function() { grecaptcha.execute(that.sitekey, { action: 'lw_form' }).then(function(token) { that.$form.find('input[name="token"],input[name="action"]').remove(); that.$form.prepend(''); that.$form.prepend(''); callback(); }); }); } else { callback(); } }, refresh: function() { var version = this.element.attr('data-version'); if (version == '' || version == 2) { grecaptcha.reset(this.widget_id); } }, getWidgetId: function() { return this.widget_id; } }); LW.frontend = { init: function() { this.initSubnavToggle(); this.initPayments(); this.initImagePreview(); if (LW.lib.getCookie(LW.cookie_prefix + 'preview')) { if ($body.hasClass('body_details')) { this.initDetailPreview(); // if lw_preview cookie found, show preview pane on details page } else { LW.lib.setCookie(LW.cookie_prefix + 'preview', '', 0, '/', LW.cookie_host, (window.location.protocol == "https:")); // if not on details page, remove cookie } } // init event detail papge if ($body.hasClass('details_events') || $body.hasClass('body_details')) { this.initEventDetailPage(); } // add aria-current="page" to self-referential links var xpath = 'a[href="'+window.location.href+'"], a[href="'+window.location.pathname+'"]'+(window.location.pathname.substr(window.location.pathname.length - 1)==='/' ? ', a[href="'+window.location.pathname+'/index.php"]' : '')+(window.location.pathname.substr(window.location.pathname.length - 10)==='/index.php' ? ', a[href="'+window.location.pathname.substr(0, window.location.pathname.length - 9)+'"]' : ''); $(xpath).attr('aria-current', 'page'); // add message for hidden content includes if (LW.lib.getQueryStringParam('include_hidden')) { var msg = 'This preview includes hidden content. View with live content only'; $('body').notify({ id: 'lw_preview_message', message: msg, type: 'warning', close_button: false, slideIn: 0 }); } // initialize the frontend behaviors in the entire body region $body.initFrontendRegion(); // init accordions if plugin present if ($.fn.lw_accordion && $('.lw_accordion').length) { $('.lw_accordion').lw_accordion(); } // if url hash refrences an anchor in an accordion, then open the accordion panel and move to it var moveToAnchorInAccordion = function(hash) { var result = false; var $anchor = $(hash); // if targeted anchor is in an accordion content block if ($anchor.length && $anchor.closest('.lw_accordion_block_content').length) { // open accordion panel var $title = $anchor.closest('.lw_accordion_block').find('.lw_accordion_block_title').trigger('click'); // move to anchor after 250 ms delay, accordion animation speed is 200ms setTimeout(function() { $('html,body').animate({ scrollTop: $title.offset().top }, 'fast'); }, 250); result = true; } return result; } if (window.location.hash) { moveToAnchorInAccordion(window.location.hash); } $(window).on('hashchange,popstate', function() { moveToAnchorInAccordion(window.location.hash); }); // randomize widgets if plugin present if ($.fn.randomize && $('.lw_widget_randomized').length) { $('.lw_widget_randomized').randomize(); } // init widget content slideshows if plugin present if ($.fn.contentSlideshow && $('.lw_widget_slideshow').length) { $('.lw_widget_slideshow').contentSlideshow(); } // init pagination if plugin present if ($.fn.paginate && $('.lw_widget_pagination:has(> .lw_paginate)').length) { $('.lw_widget_pagination:has(> .lw_paginate)').paginate(); } // init save-and-share if plugin present if ($.fn.saveandshare && $('.lw_saveandshare_email').length) { $('.lw_saveandshare_email').saveandshare(); } this.initVideo($body); this.initDetailPageMaps(); if (window.location.pathname.indexOf('.test.php') !== -1) { this.showTestingMessage(); } this.addPermalinkHandler(); $('.lw_widget_type_galleries_inline').find('img').attr('loading', 'eager'); // disable lazy loading on inline galleries }, addPermalinkHandler: function() { $body.on('click', '.lw_widget_saveandshare .permalink a', function(e) { e.preventDefault(); var $this = $(this); LW.lib.copyToClipboard(window.location.href); $this.addClass('is-copied'); setTimeout(function() { $this.removeClass('is-copied'); }, 1800); return true; }); }, initVideo: function($wrapper) { // remove width and height attributes from .lw_media if width="100%" var $lw_media = $wrapper.find('.lw_media,.lw_media_wrapper > *:not(.lw_media)').each(function() { var $this = $(this); // reset width and height if width set to 100% if ('100%' === $this.attr('width') || '100%' === $this.css('width')) { $this .removeAttr('width') .removeAttr('height') .css('width', '') .css('height', ''); } // browsers set iframe/object width and height to 300x150 by default - set to 16:9 if (300 === $this.width() && 150 === $this.height()) { // clear width/height style declarations, they override what fitvid sets $this.css('width', ''); $this.css('height', ''); // set 16:9 aspect ratio $this.attr('width', 160); $this.attr('height', 90); } }); $wrapper.fitVids({ ignore: '.lw_media_not_responsive' }); // wrap video with custom dimensions in fluid width wrapper so they shrink with browser $lw_media.filter('.lw_media_not_responsive').each(function() { var $this = $(this); var width = $this.width(); if (!$this.closest('.custom-dimension-video-wrapper').length) { $this .removeAttr('width') .removeAttr('height') .wrap('
') .wrap('
'); } }); }, initImagePreview: function() { // build array of preview images on page function getPreviewImageArray() { var images = []; $('.lw_preview_image').each(function() { var $this = $(this); var $img = $this.find('img'); images.push({ src: $this.attr('href'), caption: LW.lib.htmlDecode($img.attr('data-caption') || $img.attr('alt') || '') }); }); return images; } $body.on('click', '.lw_preview_image', function(e) { e.preventDefault(); var $this = $(this), caption = $this.find('img').eq(0).attr('alt'); if ($this.hasClass('lw_disable_preview')) return true; // set caption to empty if alt is the default 'image' if ('image' === caption) caption = ''; LW.previewImage($this.attr('href'), caption, getPreviewImageArray()); return true; }); // apply image preview to images widget items }, initDetailPreview: function() { $('
') .html('Here’s the preview you requested. Click to close window') .prependTo($body); $body.addClass('lw_is_preview'); $('.lw_close_window').on('click', function() { window.close(); return false; }); }, initIngredientsPreviewNotification: function() { // display notice when in preview mode if (LW.ingredients_preview) { var msg; msg = 'Live Preview
You are previewing unpublished changes.' + '
turn off'; $body.addClass('has_lw_notice').notify({ id: 'lw_is_hidden_message', message: msg, type: 'success', close_button: false, slideIn: 0, custom_class: 'lw_ingredients_live_preview' }); $('.js-turn-off-live-preview').on('click', function() { $.ajax({ url: '/livewhale/backend.php', data: { livewhale: 'ajax', function: 'disableIngredientsPreview' }, method: 'GET', dataType: 'json', success: function(response) { response = response || {}; if ($.isEmptyObject(response) || response.error) { LW.prompt('Error', response.error || 'Unable to disable preview mode.', 'warning'); } else { window.location.reload(true); } } }); }); } }, initHiddenPageNotification: function() { var msg; msg = 'This page is marked as hidden. It is not visible to the public.'; $body.addClass('has_lw_notice').notify({ id: 'lw_is_hidden_message', message: msg, type: 'warning', close_button: false, slideIn: 0 }); // move toolbar and page down to accomodate notification var msg_height = $('#lw_is_hidden_message').outerHeight() - 2; $('#lw_toolbar').animate({ top: msg_height }, 180); $('#lw_page').animate({ marginTop: '+=' + msg_height + 'px' }, 180); }, initSubnavToggle: function() { var $toggle = $('.lw_subnav_toggle'); // do nothing if no toggle if (!$toggle.length) return; $toggle.each(function() { // find subnav toggles $(this).on('click', function() { // add click event to toggle the submenu var subnav = $(this).next('ul'); // get subnav to toggle if (subnav.is(':visible')) { subnav.slideUp(400, function() { $(this).closest('li').removeClass('lw_expanded'); $(this).attr('aria-hidden', 'true'); $(this).prev('.lw_subnav_toggle').attr('aria-expanded', 'false'); }); } // hide if shown else { // else if not showing if ($('.lw_subnav_toggle').next('ul:visible').length) { $('.lw_subnav_toggle').next('ul:visible').slideUp(400, function() { // hide any that are shown first $(this).closest('li').removeClass('lw_expanded'); $(this).attr('aria-hidden', 'true'); $(this).prev('.lw_subnav_toggle').attr('aria-expanded', 'false'); subnav.slideDown(650, function() { // then show it $(this).closest('li').addClass('lw_expanded'); $(this).attr('aria-hidden', 'false'); $(this).prev('.lw_subnav_toggle').attr('aria-expanded', 'true'); }); }); } else { // else just show it subnav.slideDown(650, function() { $(this).closest('li').addClass('lw_expanded'); $(this).attr('aria-hidden', 'false'); $(this).prev('.lw_subnav_toggle').attr('aria-expanded', 'true'); }); } } return false; }); }); }, initPayments: function() { // load payments JS if there are payment forms if (!$('.lw_payments').length) return; $.getScript(LW.liveurl_dir + '/resource/js/livewhale/theme/core/scripts/payments.js', function() { LW.payments.init(); }); }, initDateAgoElements: function() { // do nothing if no date_ago elements if (!$('.lw_date_ago').length) return; function updateDateAgoElements() { // converts date_ago elements into a human-readable string $.each($('.lw_date_ago'), function() { // for each date_ago element if ($(this).attr('data-date')) { // if it has the required date attribute var theDate = new Date($(this).attr('data-date')); if (theDate && !isNaN(theDate.getTime())) { // and that date is valid var now = new Date(), // calculate the string elapsed = (now.getTime() - theDate.getTime()) / 1000, days = Math.floor(elapsed / 86400), hours = Math.floor((elapsed - (days * 86400)) / 3600), minutes = Math.floor((elapsed - (days * 86400) - (hours * 3600)) / 60), seconds = Math.floor((elapsed - (days * 86400) - (hours * 3600) - (minutes * 60))); $(this).html(days >= 1 ? days + ' day' + (days !== 1 ? 's' : '') + ' ago' : (hours >= 1 ? hours + ' hour' + (hours !== 1 ? 's' : '') + ' ago' : (minutes >= 1 ? minutes + ' minute' + (minutes !== 1 ? 's' : '') + ' ago' : (seconds >= 1 ? seconds + ' second' + (seconds !== 1 ? 's' : '') + ' ago' : '')))); // set the elapsed time in the element } } }); } updateDateAgoElements(); // update all date_ago elements setInterval(function() { // and refresh them every 60 seconds updateDateAgoElements(); }, 60000); }, initEventDetailPage: function() { var $add_to_cal = $('#lw_cal_add_to_calendar, .lw_cal_add_to_calendar'); if (!$add_to_cal.length) return; // show/hide add to calendar items $add_to_cal.on('click', ' > a', function(e) { e.preventDefault(); var $this = $(this), $ul = $this.parent().find('ul'); if ($ul.is(':visible')) { $this.removeClass('lw_active'); } else { $this.addClass('lw_active'); } $ul.slideToggle(200); return true; }) // handle add to calendar item click .on('click', 'li', function(e) { e.preventDefault(); var $icon = $(this).find('.lw_cal_icon'), url; if ($icon.hasClass('lw_cal_google')) { url = LW.lib.getAddToGoogleLink(LW.details_data); } else if ($icon.hasClass('lw_cal_yahoo')) { url = LW.lib.getAddToYahooLink(LW.details_data); } else if ($icon.hasClass('lw_cal_ical') || $icon.hasClass('lw_cal_outlook')) { url = LW.liveurl_dir + '/ical/events/id/' + LW.details_id + '/outlook/1'; } window.open(url, 'SaveToCalendar'); }); }, initDetailPageMaps: function() { // return right away if not a detail template or if missing map or map data if (!LW.is_details_template || !LW.latitude || !LW.longitude || !$('.details_map').length) { return false; } var $map = $('.details_map'); var aspect_ratio = $map.attr('data-aspect-ratio') ? $map.attr('data-aspect-ratio') : '1:1'; var zoom = $map.attr('data-zoom') ? $map.attr('data-zoom') : 17; $map.lwGoogleMapsEmbed({ api_key: LW.maps_api_key, latitude: LW.latitude, longitude: LW.longitude, aspect_ratio: aspect_ratio, zoom: zoom }); }, showTestingMessage: function() { var height; $body.notify({ id: 'lw_testing_message', message: 'This has been marked as a test page.', type: 'warning', close_button: false, slideIn: 0 }); height = $('#lw_testing_message').outerHeight(); $body.css('margin-top', height); // adjust toolbar and page to accomodate testing notification $body.on('pageEditorInit.lw', function() { $body.css('margin-top', 0); $('#lw_page').css('margin-top', '+=' + height); $('#lw_toolbar').css('top', height); }); } }; // on DOM ready $(function() { LW.frontend.init(); // add hidden page notification if (LW.is_hidden_page) { LW.frontend.initHiddenPageNotification(); } LW.frontend.initIngredientsPreviewNotification(); }); }(livewhale.jQuery || window.jQuery, livewhale)); /* Resource ID: 75aa3fc9331361725c5d7ea5479 ('+document.location.href.replace() */ /* Resource not found (). */ /* Resource ID: 815417267f76f6f460a4a61f9db ([) */ /* Resource not found (). */